import { ref, watchEffect, toValue } from 'vue'

/**
 * 一个用于执行网络请求的 Vue 组合式函数。
 * 当组件挂载或传入的 URL 发生变化时，自动发起数据请求。
 * 
 * @param {string | Ref<string>} url - 请求的目标 URL，可以是静态字符串或 Vue 的响应式 Ref 对象。
 * @returns {Object} 返回一个包含 data 和 error 的对象：
 *          - data: 响应的数据，初始值为 null。
 *          - error: 请求过程中发生的错误信息，初始值为 null。
 */
export function useFetch(url) {
  // 初始化响应式变量 data 和 error，分别用于存储请求返回的数据和错误信息。
  const data = ref(null)
  const error = ref(null)

  /**
   * 执行实际的网络请求逻辑。
   * 在发起请求前，重置 data 和 error 的值以确保状态一致性。
   */
  const fetchData = () => {
    data.value = null
    error.value = null

    // 使用 Fetch API 发起请求，并处理响应结果或捕获错误。
    // toValue() 是一个在 3.3 版本中新增的 API。它的设计目的是将 ref 或 getter 规范化为值。
    // 如果参数是 ref，它会返回 ref 的值；如果参数是函数，它会调用函数并返回其返回值。否则，它会原样返回参数。
    fetch(toValue(url))
      .then((res) => res.json())
      .then((json) => (data.value = json))
      .catch((err) => (error.value = err))
  }

  // 使用 watchEffect 监听 URL 的变化，当 URL 变化或组件首次渲染时自动调用 fetchData。
  // watchEffect 是 Vue Composition API 中的一个函数，它会自动追踪其依赖项，并在任何依赖项发生变化时重新运行提供的函数。
  watchEffect(() => {
    fetchData()
  })

  // 返回包含 data 和 error 的对象，供外部使用。
  return { data, error }
}